package com.zj.utils;

import com.zj.utils.eo.DateDtf;
import com.zj.utils.eo.DatePattern;
import com.zj.utils.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间处理
 *
 * @author xi.yang
 * @create 2020-11-14 11:04
 **/
public class DateUtil {
    private static ZoneId zoneId = ZoneId.systemDefault();

    private static final Logger log = LoggerFactory.getLogger(DateUtil.class);

    public static void initZone(ZoneId zone) {
        zoneId = zone;
    }

    public static Date getCurTime() {
        return new Date();
    }

    public static Date getCurDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date parseDate(String dateStr, DatePattern datePattern) {
        try {
            return new SimpleDateFormat(datePattern.getPattern()).parse(dateStr);
        } catch (ParseException e) {
        }
        return null;
    }

    public static Date getDateFirstTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getNextDateFirstTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getMonthFirstTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Date getNextMonthFirstTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 格式化指定日期格式
     *
     * @param date
     * @param datePattern
     * @return
     */
    public static String fmtDate(Date date, DatePattern datePattern) {
        String result = "";
        SimpleDateFormat formater = new SimpleDateFormat(datePattern.getPattern());
        try {
            result = formater.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * localDate转为long
     *
     * @param localDate
     * @return
     */
    public static long localDate2Long(LocalDate localDate) {
        return localDateTime2Long(localDate.atStartOfDay());
    }

    /**
     * localDateTime转long
     *
     * @param localDateTime
     * @return
     */
    public static long localDateTime2Long(LocalDateTime localDateTime) {
        return localDateTime.atZone(zoneId).toInstant().toEpochMilli();
    }

    /**
     * 获取一周的开始时间
     *
     * @param time
     * @return
     */
    public static long getWeekStartTime(long time) {
        LocalDate localDate = long2LocalDate(time);
        int dayOfWeek = localDate.getDayOfWeek().getValue();
        return localDate2Long(localDate.plusDays(-dayOfWeek + 1));
    }

    /**
     * 获取当前时间戳
     *
     * @return
     */
    public static long currentTimeMillis() {
        return localDateTime2Long(curLocalDateTime());
    }

    public static LocalDateTime curLocalDateTime() {
        return LocalDateTime.now(zoneId);
    }

    public static LocalDate curLocalDate() {
        return LocalDate.now(zoneId);
    }

    public static LocalDateTime long2LocalDateTime(long time) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(time), zoneId);
    }

    public static LocalDate long2LocalDate(long time) {
        return long2LocalDateTime(time).toLocalDate();
    }

    public static LocalDateTime string2LocalDateTime(String timeStr, DateDtf dtf) {
        if (!dtf.isStrProcess()) {
            return LocalDateTime.parse(timeStr, dtf.getFormatter());
        }
        switch (dtf) {
            case MMdd_HHmm:
                return LocalDateTime.parse(curLocalDateTime().getYear() + "-" + timeStr, DateDtf.yyyyMMdd_HHmm.getFormatter());
            case yyyyMM:
                return LocalDate.parse(timeStr + "-" + curLocalDate().getDayOfMonth(), DateDtf.yyyyMMdd.getFormatter()).atStartOfDay();
            case yyyyMMdd:
                // 这些都是直接转日期的
            case yyyyMMdd_ch:
            case yyMMdd_mini:
            case yyyyMMdd_mini:
                return LocalDate.parse(timeStr, dtf.getFormatter()).atStartOfDay();
            case HHmmss:
            case HHmm:
                return LocalTime.parse(timeStr, dtf.getFormatter()).atDate(curLocalDate());
        }
        throw new ServiceException("not define trans dtf [{}]" + dtf);
    }

    public static String long2String(long time, DateDtf dtf) {
        return dtf.getFormatter().format(long2LocalDateTime(time));
    }

    /**
     * 两个时间是否为同一周
     *
     * @param first
     * @param second
     * @return
     */
    private static boolean isSameWeek(LocalDateTime first, LocalDateTime second) {
        return isSameWeek(first.toLocalDate(), second.toLocalDate());
    }

    /**
     * 两个时间是否为同一周
     *
     * @param first
     * @param second
     * @return
     */
    public static boolean isSameWeek(LocalDate first, LocalDate second) {
        LocalDate min, max;
        if (first.isBefore(second)) {
            min = first;
            max = second;
        } else {
            min = second;
            max = first;
        }
        Period period = Period.between(min, max);
        int days = period.getDays();
        // 同一天
        if (days == 0) {
            return true;
        }
        if (days > 6) {
//            两个时间差 超出了7天
            return false;
        }
        return min.plusDays(8 - min.getDayOfWeek().getValue()).isAfter(max);
    }
}
